package cn.sunjinxin.trade.domain.model;

import cn.sunjinxin.trade.domain.enums.BizType;
import cn.sunjinxin.trade.domain.enums.OrderType;
import cn.sunjinxin.trade.domain.model.entity.Distributor;
import cn.sunjinxin.trade.domain.model.entity.Money;
import cn.sunjinxin.trade.domain.model.entity.Traveler;
import cn.sunjinxin.trade.domain.status.*;
import lombok.Getter;
import lombok.Setter;

import java.util.*;


/**
 * 订单
 *
 * @author issavior
 */
@Getter
public class Order {

    /**
     * 订单Id
     */
    private Long id;

    /**
     * 分销商
     */
    private Distributor distributor;

    /**
     * 订单类型
     */
    private OrderType orderType;

    /**
     * 业务编码
     */
    private BizType bizCodeEnum;

    /**
     * 订单关联的产品sku
     */
    private ProductSpu productSpu;

    /**
     * 订单状态
     */
    private OrderStatus orderStatus;

    /**
     * 支付状态
     */
    private PayStatus payStatus;

    /**
     * 关单原因
     */
    private String closeReason;

    /**
     * 关单时间
     */
    private Date closeTime;

    /**
     * 退款状态
     */
    private RefundStatus refundStatus;

    /**
     * 交付状态
     */
    private PerformanceStatus performanceStatus;

    /**
     * 支付金额
     */
    private Money payFee;

    /**
     * 关联的游客
     */
    private List<Traveler> travellers;

    /**
     * 服务开始时间
     */
    private Date serviceStartTime;

    /**
     * 服务结束时间
     */
    private Date serviceEndTime;

    /**
     * 乐观锁
     */
    private Integer version;

    /**
     * 创建时间
     */
    private Date gmtCreate;

    /**
     * 修改时间
     */
    private Date gmtModified;

    @Setter
    private List<Order> childOrders;

    /**
     * 扩展字段
     */
    private Map<String, String> attributes;


    public static Order initOrder(OrderType orderType, ProductSpu productSpu, Distributor distributor, List<Traveler> travellers) {
        Order order = new Order();
        order.id = 1L;
        order.orderType = orderType;
        order.bizCodeEnum = productSpu.getProductBizType();
        order.productSpu = productSpu;
        order.distributor = distributor;
        order.travellers = travellers;
        initOrderStatus(order);
        return order;
    }

    private static void initOrderStatus(Order order) {
        order.orderStatus = OrderStatus.ORDER_INIT;
        order.payStatus = PayStatus.TO_BE_PAID;
        order.refundStatus = RefundStatus.NO_REFUND_ORDER_INIT;
        order.performanceStatus = PerformanceStatus.NO_PERFORMANCE;

        order.attributes = new HashMap<>();
    }

    public Order addPayFee(Money payFee) {
        this.payFee = payFee;
        return this;
    }

    public void initId(Long id) {
        this.id = id;
    }

    // todo
    public boolean isPaid() {
        return this.payStatus == PayStatus.PAID;
    }

    public boolean isNotPaid() {
        return !isPaid();
    }

    public boolean isInit() {
        return orderStatus == OrderStatus.ORDER_INIT;
    }

    public boolean isEnd() {
        return this.orderStatus == OrderStatus.ORDER_TRADE_SUCCESS || this.orderStatus == OrderStatus.ORDER_TRADE_CLOSE || this.orderStatus == OrderStatus.ORDER_TRADE_CANCEL;
    }

    public boolean notRefund() {
        return this.refundStatus == RefundStatus.REFUND_ORDER_INIT;
    }

    public boolean isRefunding() {
        return this.refundStatus == RefundStatus.REFUNDING;
    }

    public boolean isRefundEnd() {
        return this.refundStatus == RefundStatus.REFUND_SUCCESS || this.refundStatus == RefundStatus.REFUND_FAIL;
    }

}